home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / lib / rexx / place.c next >
C/C++ Source or Header  |  1997-09-09  |  11KB  |  521 lines

  1.  
  2. /*
  3.  *  PLACE.C
  4.  *
  5.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  6.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  7.  *    DICE-LICENSE.TXT.
  8.  *
  9.  *  PlaceRexxCommand()
  10.  *
  11.  *  Send an AREXX command according to arguments and RexxHostName
  12.  */
  13.  
  14. #include "rexx/rexx.h"
  15.  
  16. void ClearDiceRexxPort(MsgPort *);
  17. void RexxReply(void *, long, char *);
  18.  
  19. static MsgPort RexxPort;            /*    master port    */
  20. static char    *RexxPortName = "REXX";      /*  master port name    */
  21.  
  22. static short    GlobalFlag;
  23. static short    MasterPortValid;
  24.  
  25. static List    RexxWIPList;
  26. static List    RexxRIPList;
  27. static List    RexxAuxPortList;
  28. static short    RexxPortInitialized;
  29.  
  30. short    RexxSigBit;    /*  master signal   */
  31.  
  32. __autoinit
  33. static void
  34. __dice_rexx_init()
  35. {
  36.     /*
  37.      *    initialize the list that tracks rexx requests sent
  38.      */
  39.  
  40.     RexxWIPList.lh_Head = (Node *)&RexxWIPList.lh_Tail;
  41.     RexxWIPList.lh_TailPred = (Node *)&RexxWIPList.lh_Head;
  42.  
  43.     /*
  44.      *    initialize the list that tracks rexx requests received
  45.      */
  46.  
  47.     RexxRIPList.lh_Head = (Node *)&RexxRIPList.lh_Tail;
  48.     RexxRIPList.lh_TailPred = (Node *)&RexxRIPList.lh_Head;
  49.  
  50.     /*
  51.      *    initialize the auxillary port list and add our master node to
  52.      *    it.
  53.      */
  54.  
  55.     RexxAuxPortList.lh_Head = (Node *)&RexxAuxPortList.lh_Tail;
  56.     RexxAuxPortList.lh_TailPred = (Node *)&RexxAuxPortList.lh_Head;
  57.  
  58.     /*
  59.      *    Get our master signal and create master port
  60.      */
  61.  
  62.     RexxSigBit = AllocSignal(-1);
  63.  
  64.     if (RexxHostName)
  65.     CreateDiceRexxPort(NULL, RexxHostName);
  66.  
  67.     RexxPortInitialized = 1;
  68. }
  69.  
  70. /*
  71.  *  The exit code can be called at any point... there might be multiple
  72.  *  messages queued, in the queue, or in processing.  We must do the
  73.  *  following items in order:
  74.  *
  75.  *    (1) prevent any further messages from being received
  76.  *    (2) return any messages queued-in or in processing
  77.  *    (3) wait for any outgoing messages to be returned
  78.  */
  79.  
  80. __autoexit
  81. static void
  82. __dice_rexx_exit()
  83. {
  84.     if (RexxPortInitialized) {
  85.     RexxPortNode *rp;
  86.  
  87.     /*
  88.      *  prevent further messages from being received
  89.      */
  90.  
  91.     for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head; rp->rp_Node.ln_Succ; rp = (RexxPortNode *)rp->rp_Node.ln_Succ) {
  92.         if (rp->rp_IsPublic) {
  93.         RemPort(rp->rp_MsgPort);
  94.         rp->rp_IsPublic = 0;
  95.         }
  96.     }
  97.  
  98.     /*
  99.      *  return any messages in processing or queued-in
  100.      */
  101.  
  102.     for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head; rp->rp_Node.ln_Succ; rp = (RexxPortNode *)rp->rp_Node.ln_Succ)
  103.         ClearDiceRexxPort(rp->rp_MsgPort);
  104.  
  105.     /*
  106.      *  wait for replies from rexx commands we have sent.  Since we
  107.      *  have cleared all other messages, no lockout conditions can
  108.      *  occur at this point.
  109.      */
  110.  
  111.     {
  112.         RexxIPNode *rip;
  113.  
  114.         while (rip = (RexxIPNode *)RemHead(&RexxWIPList)) {
  115.         if (rip->rip_Returned == 0) {
  116.             while (((Message *)rip->rip_RexxMsg)->mn_Node.ln_Type != NT_REPLYMSG)
  117.             Wait(1 << RexxSigBit);
  118.             Forbid();
  119.             Remove(&rip->rip_RexxMsg->rm_Node.mn_Node);
  120.             Permit();
  121.             rip->rip_Returned = 1;
  122.         }
  123.         ClearRexxMsg(rip->rip_RexxMsg, 1);
  124.         DeleteRexxMsg(rip->rip_RexxMsg);
  125.         }
  126.     }
  127.  
  128.     /*
  129.      *  Delete the ports.  Since we have cleared rp_IsPublic it will
  130.      *  not try to RemPort() them again.
  131.      */
  132.  
  133.     while ((rp = (RexxPortNode *)RexxAuxPortList.lh_Head) != (RexxPortNode *)&RexxAuxPortList.lh_Tail)
  134.         DeleteDiceRexxPort(rp->rp_MsgPort);
  135.  
  136.     /*
  137.      *  Free our master signal
  138.      */
  139.  
  140.     FreeSignal(RexxSigBit);
  141.     RexxPortInitialized = 0;
  142.     }
  143. }
  144.  
  145. long
  146. PlaceRexxCommandDirect(port, remoteName, arg, pres, pec)
  147. MsgPort *port;
  148. char *remoteName;
  149. char *arg;
  150. char **pres;
  151. long *pec;
  152. {
  153.     char *rpn = RexxPortName;
  154.     long r;
  155.  
  156.     RexxPortName = remoteName;
  157.     r = PlaceRexxCommand(port, arg, pres, pec);
  158.     RexxPortName = rpn;
  159.     return(r);
  160. }
  161.  
  162. long
  163. PlaceRexxCommand(port, arg, pres, pec)
  164. MsgPort *port;
  165. char *arg;
  166. char **pres;
  167. long *pec;
  168. {
  169.     RexxIPNode rip;
  170.     long rc = -2;
  171.  
  172.     if (port == NULL) {
  173.     if (MasterPortValid == 0)
  174.         return(-1);
  175.     port = &RexxPort;
  176.     }
  177.  
  178.     if (pres)
  179.     *pres = NULL;
  180.     if (pec)
  181.     *pec = 0;
  182.  
  183.  
  184.     if (RexxSysBase) {
  185.     rc = -1;
  186.  
  187.     if (rip.rip_RexxMsg = CreateRexxMsg(port, ((RexxHostName) ? RexxHostName : "UNKNOWN"), port->mp_Node.ln_Name)) {
  188.         MsgPort *arexxPort;
  189.  
  190.         rip.rip_RexxMsg->rm_Node.mn_Node.ln_Name = "REXX";
  191.         rip.rip_RexxMsg->rm_Action = RXCOMM;
  192.         if (pres) rip.rip_RexxMsg->rm_Action |= RXFF_RESULT;
  193.         ARG0(rip.rip_RexxMsg) = CreateArgstring(arg,strlen(arg));
  194.  
  195.         AddHead(&RexxWIPList, &rip.rip_Node);
  196.         rip.rip_Returned = 0;
  197.         rip.rip_RexxPort = port;
  198.  
  199.         Forbid();
  200.         if (arexxPort = (MsgPort *)FindPort(RexxPortName)) {
  201.         PutMsg(arexxPort, (Message *)rip.rip_RexxMsg);
  202.         Permit();
  203.  
  204.         while (rip.rip_Returned == 0) {
  205.             RexxPortNode *rp;
  206.  
  207.             /*
  208.              *    Since this is the only wait on this signal there
  209.              *    can be no lockout condition.
  210.              */
  211.  
  212.             Wait(1 << RexxSigBit);
  213.             for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head; rp->rp_Node.ln_Succ; rp = (RexxPortNode *)(rp->rp_Node.ln_Succ))
  214.             ProcessRexxCommands(rp->rp_MsgPort);
  215.         }
  216.         } else {
  217.         Permit();
  218.         }
  219.         Remove(&rip.rip_Node);
  220.  
  221.         /*
  222.          *    Process result / return code here if rip.rip_Returned == 0
  223.          *    then we were not able to dispatch the message
  224.          */
  225.  
  226.         if (rip.rip_Returned) {
  227.         if ((rc = rip.rip_RexxMsg->rm_Result1) == 0) {
  228.             if (rip.rip_RexxMsg->rm_Result2) {
  229.                 if (pres)
  230.                 *pres = strdup((char *)rip.rip_RexxMsg->rm_Result2);
  231.             DeleteArgstring((UBYTE *)rip.rip_RexxMsg->rm_Result2);
  232.             }
  233.         } else {
  234.             if (pec)
  235.             *pec = (long)rip.rip_RexxMsg->rm_Result2;
  236.         }
  237.         }
  238.         ClearRexxMsg(rip.rip_RexxMsg, 1);
  239.         DeleteRexxMsg(rip.rip_RexxMsg);
  240.     }
  241.     }
  242.     return(rc);
  243. }
  244.  
  245. void
  246. ProcessRexxCommands(port)
  247. MsgPort *port;
  248. {
  249.     RexxMsg *msg;
  250.  
  251.     if (port == NULL) {
  252.     RexxPortNode *rp;
  253.  
  254.     for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head; rp->rp_Node.ln_Succ; rp = (RexxPortNode *)(rp->rp_Node.ln_Succ))
  255.         ProcessRexxCommands(rp->rp_MsgPort);
  256.     return;
  257.     }
  258.  
  259.     while (msg = (struct RexxMsg *)GetMsg(port)) {
  260.     if ((msg->rm_Node.mn_Node.ln_Type == NT_MESSAGE) && IsRexxMsg(msg)) {
  261.         RexxIPNode rip;
  262.         char *str = NULL;
  263.         long rc;
  264.  
  265.         rip.rip_RexxMsg = msg;
  266.         rip.rip_RexxPort = port;
  267.         AddTail(&RexxRIPList, &rip.rip_Node);
  268.         rc = DoRexxCommand(msg, port, ARG0(msg), &str);
  269.         Remove(&rip.rip_Node);
  270.         RexxReply(msg, rc, str);
  271.     } else {
  272.         RexxIPNode *rip;
  273.  
  274.         for (rip = (RexxIPNode *)RexxWIPList.lh_Head; rip->rip_Node.ln_Succ; rip = (RexxIPNode *)rip->rip_Node.ln_Succ) {
  275.         if (msg == rip->rip_RexxMsg) {
  276.             rip->rip_Returned = 1;
  277.             break;
  278.         }
  279.         }
  280.     }
  281.     }
  282. }
  283.  
  284. /*
  285.  *  Create a global DICE rexx port
  286.  */
  287.  
  288. short
  289. CreateGlobalDiceRexxPort(port, name)
  290. MsgPort *port;
  291. char *name;
  292. {
  293.     short r;
  294.  
  295.     GlobalFlag = 1;
  296.     r = CreateDiceRexxPort(port, name);
  297.     GlobalFlag = 0;
  298.  
  299.     return(r);
  300. }
  301.  
  302. /*
  303.  *  Create an application DICE rexx port
  304.  */
  305.  
  306. short
  307. CreateDiceRexxPort(port, name)
  308. MsgPort *port;
  309. char *name;
  310. {
  311.     RexxPortNode *rp;
  312.     short pno;
  313.     short isPublic;
  314.     short allocSize;
  315.  
  316.     if (port == NULL) {
  317.     port = &RexxPort;
  318.     MasterPortValid = 1;
  319.     }
  320.  
  321.     if (name == NULL) {
  322.     name = "PRIVATE-REXX-PORT";
  323.     isPublic = 0;
  324.     } else {
  325.     isPublic = 1;
  326.     }
  327.     allocSize = sizeof(RexxPortNode) + strlen(name) + 4;
  328.  
  329.     rp = AllocMem(allocSize, MEMF_PUBLIC|MEMF_CLEAR);
  330.  
  331.     rp->rp_Node.ln_Type = allocSize;
  332.     rp->rp_MsgPort = port;
  333.     rp->rp_IsPublic = isPublic;
  334.     AddTail(&RexxAuxPortList, &rp->rp_Node);
  335.  
  336.     port->mp_Node.ln_Name = (char *)(rp + 1);
  337.  
  338.     port->mp_Node.ln_Type = NT_MSGPORT;
  339.     port->mp_Node.ln_Pri = 1;
  340.     port->mp_Flags = PA_SIGNAL;
  341.     port->mp_SigBit = RexxSigBit;
  342.     port->mp_SigTask = FindTask(NULL);
  343.     port->mp_MsgList.lh_Head = (Node *)&port->mp_MsgList.lh_Tail;
  344.     port->mp_MsgList.lh_TailPred = (Node *)&port->mp_MsgList.lh_Head;
  345.  
  346.     /*
  347.      *    Give the port a real name according to AREXX semantics,
  348.      *    portname.NN (01-99)
  349.      */
  350.  
  351.     Forbid();
  352.  
  353.     if (GlobalFlag || isPublic == 0) {
  354.     strcpy(port->mp_Node.ln_Name, name);
  355.     if (isPublic && FindPort(port->mp_Node.ln_Name))
  356.         pno = -1;
  357.     else
  358.         pno = 0;
  359.     } else {
  360.     for (pno = 1; pno < 100; ++pno) {
  361.         char buf[4];
  362.         strcpy(buf, ".00");
  363.         buf[1] += pno / 10;
  364.         buf[2] += pno % 10;
  365.         strcpy(port->mp_Node.ln_Name, name);
  366.         strcat(port->mp_Node.ln_Name, buf);
  367. /*        sprintf(port->mp_Node.ln_Name, "%s.%02d", name, pno); */
  368.         if (FindPort(port->mp_Node.ln_Name) == NULL)
  369.         break;
  370.     }
  371.     if (pno == 100)
  372.         pno = -1;
  373.     }
  374.  
  375.     if (isPublic)
  376.     AddPort(port);
  377.  
  378.     if (pno < 0)
  379.     DeleteDiceRexxPort(port);
  380.     else if (port == (MsgPort *)&RexxPort && RexxHostName == NULL)
  381.     RexxHostName = port->mp_Node.ln_Name;
  382.  
  383.     Permit();
  384.  
  385.     return(pno);
  386. }
  387.  
  388. /*
  389.  *  Delete a DICE rexx port.  Note that there can be no outgoing messages
  390.  *  in-progress for this port for this command to work properly.
  391.  */
  392.  
  393. void
  394. DeleteDiceRexxPort(port)
  395. MsgPort *port;
  396. {
  397.     /*
  398.      *    check if valid port, remove RexxPortNode if found
  399.      */
  400.  
  401.     {
  402.     RexxPortNode *rp;
  403.  
  404.     for (rp = (RexxPortNode *)RexxAuxPortList.lh_Head; rp->rp_Node.ln_Succ; rp = (RexxPortNode *)rp->rp_Node.ln_Succ) {
  405.         if (rp->rp_MsgPort == port) {
  406.         Remove(&rp->rp_Node);
  407.         if (rp->rp_IsPublic)
  408.             RemPort(port);
  409.         FreeMem(rp, rp->rp_Node.ln_Type);
  410.         break;
  411.         }
  412.     }
  413.     if (rp == NULL)
  414.         return;
  415.     }
  416.  
  417.     ClearDiceRexxPort(port);
  418.  
  419.     /*
  420.      *    clear port info
  421.      */
  422.  
  423.     clrmem(port, sizeof(MsgPort));
  424.  
  425.     if (port == (MsgPort *)&RexxPort)
  426.     MasterPortValid = 0;
  427. }
  428.  
  429. void
  430. ClearDiceRexxPort(port)
  431. MsgPort *port;
  432. {
  433.     /*
  434.      *    kill any received messages that are in progress
  435.      */
  436.  
  437.     {
  438.     RexxIPNode *rip;
  439.     RexxIPNode *rip_next;
  440.  
  441.     for (rip = (RexxIPNode *)RexxRIPList.lh_Head; rip->rip_Node.ln_Succ; rip = rip_next) {
  442.         rip_next = (RexxIPNode *)rip->rip_Node.ln_Succ;
  443.         if (rip->rip_RexxPort == port) {
  444.         Remove(&rip->rip_Node);
  445.         RexxReply(rip->rip_RexxMsg, 30, NULL);
  446.         }
  447.     }
  448.     }
  449.  
  450.  
  451.     /*
  452.      *    clear out any messages pending on the port
  453.      */
  454.  
  455.     {
  456.     RexxMsg *msg;
  457.  
  458.     while (msg = (RexxMsg *)GetMsg(port)) {
  459.         if ((msg->rm_Node.mn_Node.ln_Type == NT_MESSAGE) && IsRexxMsg(msg)) {
  460.         RexxReply(msg, 30, NULL);
  461.         } else {
  462.         RexxIPNode *rip;
  463.  
  464.         for (rip = (RexxIPNode *)RexxWIPList.lh_Head; rip->rip_Node.ln_Succ; rip = (RexxIPNode *)rip->rip_Node.ln_Succ) {
  465.             if (msg == rip->rip_RexxMsg) {
  466.             rip->rip_Returned = 1;
  467.             break;
  468.             }
  469.         }
  470.         }
  471.     }
  472.     }
  473. }
  474.  
  475. void
  476. RexxReply(vmsg, res1, str)
  477. void *vmsg;
  478. long res1;
  479. char *str;
  480. {
  481.     RexxMsg *msg = vmsg;
  482.  
  483.     if (msg->rm_Result1 = res1) {
  484.     msg->rm_Result2 = NULL;
  485.     } else {
  486.     if (str)
  487.         msg->rm_Result2 = (long)CreateArgstring(str, strlen(str));
  488.     else
  489.         msg->rm_Result2 = NULL;
  490.     }
  491.     ReplyMsg((Message *)msg);
  492. }
  493.  
  494. /*
  495.  *  Obtain the fully qualified name of an application port (name.xx) and
  496.  *  return an integer.    Returns -1 if the port does not contain a .xx
  497.  *  extension.
  498.  */
  499.  
  500. int
  501. GetDiceRexxPortSlot(port, pname)
  502. MsgPort *port;
  503. char **pname;
  504. {
  505.     int slotNo = -1;
  506.     char *ptr;
  507.  
  508.     if (port == NULL)
  509.     port = &RexxPort;
  510.     if (ptr = strrchr(port->mp_Node.ln_Name, '.')) {
  511.     char *tmp;
  512.  
  513.     slotNo = strtol(ptr + 1, &tmp, 10);  /* must be base 10 re: '.01'... */
  514.     if (tmp == ptr)
  515.         slotNo = -1;
  516.     }
  517.     if (pname)
  518.     *pname = port->mp_Node.ln_Name;
  519.     return(slotNo);
  520. }
  521.